﻿using System;
using System.Collections.Generic;
using System.Text;
using System.Windows.Input;
using System.Windows;
using System.Windows.Automation;
using System.Windows.Controls;
using System.Windows.Media;
using System.Windows.Shapes;
using Microsoft.Windows.Design.Interaction;
using Microsoft.Windows.Design.Model;

namespace AutoSizeButtonLibrary.VisualStudio.Design
{
    // The following class implements an adorner provider for the 
    // AutoSizeButton control. The adorner is a CheckBox control, which 
    // changes the Height and Width of the AutoSizeButton to "Auto",
    // which is represented by double.NaN.
    public class AutoSizeAdornerProvider : PrimarySelectionAdornerProvider
    {
        private ModelItem adornedControlModel = null;
        CheckBox autoSizeCheckBox = new CheckBox();

        // The constructor sets up the adorner control. 
        public AutoSizeAdornerProvider()
        {
            autoSizeCheckBox.Content = "AutoSize";
            autoSizeCheckBox.IsChecked = true;
            autoSizeCheckBox.FontFamily = AdornerFonts.FontFamily;
            autoSizeCheckBox.FontSize = AdornerFonts.FontSize;
            autoSizeCheckBox.Background = AdornerResources.FindResource(
                AdornerColors.RailFillBrushKey) as Brush;
        }

        // The following method is called when the adorner is activated.
        // It creates the adorner control, sets up the adorner panel,
        // and attaches a ModelItem to the AutoSizeButton.
        protected override void Activate(ModelItem item, DependencyObject view)
        {
            // Save the ModelItem and hook into when it changes.
            // This enables updating the slider position when 
            // a new background value is set.
            adornedControlModel = item;
            adornedControlModel.PropertyChanged +=
                new System.ComponentModel.PropertyChangedEventHandler(
                    AdornedControlModel_PropertyChanged);

            // All adorners are placed in an AdornerPanel
            // for sizing and layout support.
            AdornerPanel autoSizeAdornerPanel = new AdornerPanel();

            // Set up the adorner's placement.
            AdornerPlacementCollection placement = new AdornerPlacementCollection();
            AdornerPanel.SetHorizontalStretch(autoSizeCheckBox, AdornerStretch.None);
            AdornerPanel.SetVerticalStretch(autoSizeCheckBox, AdornerStretch.None);

            autoSizeAdornerPanel.CoordinateSpace = AdornerCoordinateSpaces.Layout;

            placement.SizeRelativeToAdornerDesiredWidth(1.0, 0);
            placement.SizeRelativeToAdornerDesiredHeight(1.0, 0);
            placement.PositionRelativeToAdornerHeight(-1.0, -23);
            placement.PositionRelativeToAdornerWidth(0, -23);

            AdornerPanel.SetPlacements(autoSizeCheckBox, placement);

            // Add the adorner to the adorner panel.
            autoSizeAdornerPanel.Children.Add(autoSizeCheckBox);

            // Listen for changes to the checked state.
            autoSizeCheckBox.Checked += new RoutedEventHandler(autoSizeCheckBox_Checked);
            autoSizeCheckBox.Unchecked += new RoutedEventHandler(autoSizeCheckBox_Unchecked);

            // Add the panel to the Adorners collection.
            Adorners.Add(autoSizeAdornerPanel);

            // Run the base implementation.
            base.Activate(item, view);
        }

        // The following code handles the Checked event.
        // It autosizes the adorned control's Height and Width.
        void autoSizeCheckBox_Checked(object sender, RoutedEventArgs e)
        {
            this.SetHeightAndWidth(true);
        }

        // The following code handles the Unchecked event.
        // It sets the adorned control's Height and Width to a hard-coded value.
        void autoSizeCheckBox_Unchecked(object sender, RoutedEventArgs e)
        {
            this.SetHeightAndWidth(false);
        }

        // The SetHeightAndWidth utility method sets the Height and Width
        // properties through the model and commits the change.
        private void SetHeightAndWidth(bool autoSize)
        {
            using (ModelEditingScope batchedChange = adornedControlModel.BeginEdit())
            {
                ModelProperty widthProperty =
                    adornedControlModel.Properties[Control.WidthProperty];

                ModelProperty heightProperty =
                    adornedControlModel.Properties[Control.HeightProperty];

                if (autoSize)
                {
                    widthProperty.ClearValue();
                    heightProperty.ClearValue();
                }
                else
                {
                    widthProperty.SetValue(20d);
                    heightProperty.SetValue(20d);
                }

                batchedChange.Complete();
            }
        }

        // The following method deactivates the adorner.
        protected override void Deactivate()
        {
            adornedControlModel.PropertyChanged -=
                new System.ComponentModel.PropertyChangedEventHandler(
                    AdornedControlModel_PropertyChanged);

            base.Deactivate();
        }

        // The following method handles the PropertyChanged event.
        void AdornedControlModel_PropertyChanged(
            object sender,
            System.ComponentModel.PropertyChangedEventArgs e)
        {
            if (e.PropertyName == "Height" || e.PropertyName == "Width")
            {
                //double h = (double)adornedControlModel.Properties[Control.HeightProperty].ComputedValue;
                //double w = (double)adornedControlModel.Properties[Control.WidthProperty].ComputedValue;

                //autoSizeCheckBox.IsChecked = (h == double.NaN && w == double.NaN) ? true : false;
            }
        }
    }
}